home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / timidsrc.zip / motif_i.c < prev    next >
C/C++ Source or Header  |  1996-05-20  |  36KB  |  1,164 lines

  1. /* 
  2.    
  3.    TiMidity -- Experimental MIDI to WAVE converter
  4.    Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
  5.    
  6.    This program is free software; you can redistribute it and/or modify
  7.    it under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 2 of the License, or
  9.    (at your option) any later version.
  10.    
  11.    This program is distributed in the hope that it will be useful,
  12.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.    GNU General Public License for more details.
  15.    
  16.    You should have received a copy of the GNU General Public License
  17.    along with this program; if not, write to the Free Software
  18.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.    
  20.    motif_interface.c: written by Vincent Pagel (pagel@loria.fr) 10/4/95
  21.    
  22.    Policy : I choose to make a separate process for a TIMIDITY motif 
  23.    interface for TIMIDITY (if the interface was in the same process
  24.    X redrawings would interfere with the audio computation. Besides 
  25.    XtAppAddWorkProc mechanism is not easily controlable)
  26.    
  27.    The solution : I create a pipe between Timidity and the forked interface
  28.    and use XtAppAddInput to watch the data arriving on the pipe.
  29.  
  30.    10/4/95 
  31.      - Initial working version with prev, next, and quit button and a
  32.        text display
  33.  
  34.    17/5/95 
  35.      - Add timidity icon with filename displaying to play midi while 
  36.        I work without having that big blue window in the corner of 
  37.        my screen :)
  38.      - Solve the problem of concurent scale value modification
  39.  
  40.    21/5/95
  41.      - Add menus, file selection box
  42.    
  43.    14/6/95
  44.      - Make the visible part of file list follow the selection
  45.  
  46.    */
  47.  
  48. #include <stdio.h>
  49. #include <stdlib.h>
  50. #include <unistd.h>
  51. #include <stdarg.h>
  52.  
  53. #include <Xm/Xm.h>
  54. #include <Xm/Form.h>
  55. #include <Xm/Text.h>
  56. #include <Xm/PushB.h>
  57. #include <Xm/Label.h>
  58. #include <Xm/Scale.h>
  59. #include <Xm/List.h>
  60. #include <Xm/Frame.h>
  61. #include <Xm/RowColumn.h>
  62. #include <Xm/CascadeB.h>
  63. #include <Xm/FileSB.h>
  64. #include <Xm/FileSB.h>
  65. #include <Xm/ToggleB.h>
  66.  
  67. #include "config.h"
  68. #include "common.h"
  69. #include "instrum.h"
  70. #include "playmidi.h"
  71. #include "output.h"
  72. #include "controls.h"
  73. #include "motif.h"
  74.  
  75. XtAppContext context;
  76. XmStringCharSet char_set=XmSTRING_DEFAULT_CHARSET;
  77.  
  78. Widget toplevel;
  79.  
  80. Widget text;
  81. static XmTextPosition wpr_position=0;
  82.  
  83. Widget mainForm; 
  84.  
  85. Widget menu_bar, open_option, quit_option, auto_next_option;
  86. Widget open_dialog , add_all_button;
  87.  
  88. Widget btnForm, backBtn,fwdBtn, restartBtn, pauseBtn, quitBtn,
  89.        nextBtn, prevBtn;
  90.  
  91. Pixmap backPixmap, fwdPixmap, pausePixmap , restartPixmap, 
  92.        playPixmap, prevPixmap, nextPixmap, quitPixmap,
  93.        timidityPixmap;
  94.  
  95. Widget countFrame, countForm, counterlbl, totlbl , count_headlbl;
  96. int last_sec=0;
  97. int max_sec=0;
  98.  
  99. Widget file_namelbl, file_headlbl;
  100.  
  101. Widget volume_scale , locator_scale ;
  102. Boolean locator_scale_button= ButtonRelease;
  103.  
  104. Widget file_list;
  105. int file_number_to_play; /* Number of the file we're playing in the list */
  106.  
  107. /*
  108.  * CREATE PIXMAPS FOR THE BUTONS
  109.  */
  110. void CreatePixmaps(Widget parent)
  111. {
  112.   /*
  113.    * 
  114.    * BITMAPS 
  115.    */
  116.     #include "BITMAPS/back.xbm"
  117.     #include "BITMAPS/next.xbm"
  118.     #include "BITMAPS/prev.xbm"
  119.     #include "BITMAPS/restart.xbm"
  120.     #include "BITMAPS/fwd.xbm"
  121.     #include "BITMAPS/pause.xbm"
  122.     #include "BITMAPS/quit.xbm"
  123.     #include "BITMAPS/timidity.xbm"
  124.  
  125.     Display *disp;
  126.     Drawable d;
  127.     Pixel fg,bg;
  128.     int ac;
  129.     Arg al[20];
  130.     unsigned int depth=DefaultDepthOfScreen(XtScreen(toplevel));
  131.  
  132.     ac = 0;
  133.     XtSetArg(al[ac], XmNbackground, &bg); ac++;
  134.     XtSetArg(al[ac], XmNforeground, &fg); ac++;
  135.     XtGetValues(parent, al, ac);
  136.  
  137.     disp=XtDisplay(toplevel);
  138.     d=RootWindowOfScreen(XtScreen(toplevel));
  139.     
  140.     backPixmap = XCreatePixmapFromBitmapData(disp, d,
  141.                          back_bits, back_width, back_height,
  142.                          fg, bg,depth);
  143.     fwdPixmap = XCreatePixmapFromBitmapData( disp, d,
  144.                          fwd_bits, fwd_width, fwd_height,
  145.                          fg, bg,depth);
  146.     pausePixmap = XCreatePixmapFromBitmapData(disp, d,
  147.                     pause_bits, pause_width, pause_height,
  148.                     fg, bg,depth);
  149.     
  150.     restartPixmap = XCreatePixmapFromBitmapData(disp, d,
  151.                       restart_bits, restart_width, restart_height,
  152.                       fg, bg,depth);
  153.     
  154.     nextPixmap  = XCreatePixmapFromBitmapData(disp, d,
  155.                     next_bits, next_width, next_height,
  156.                     fg, bg,depth);
  157.     
  158.     prevPixmap  = XCreatePixmapFromBitmapData(disp, d,
  159.                     prev_bits, prev_width, prev_height,
  160.                     fg, bg,depth);
  161.     
  162.     quitPixmap  = XCreatePixmapFromBitmapData(disp, d,
  163.                     quit_bits, quit_width, quit_height,
  164.                     fg, bg,depth);
  165.  
  166.     timidityPixmap  = XCreatePixmapFromBitmapData(disp, d,
  167.                           timidity_bits, timidity_width, timidity_height,
  168.                           WhitePixelOfScreen(XtScreen(toplevel)),
  169.                           BlackPixelOfScreen(XtScreen(toplevel)),depth);
  170. }
  171.  
  172.  
  173. /************************************
  174.  *                                  *
  175.  * ALL THE INTERFACE'S CALLBACKS    *
  176.  *                                  *
  177.  ************************************/
  178.  
  179. /*
  180.  * Generic buttons callbacks ( Transport Buttons )
  181.  */
  182. void  GenericCB(Widget widget, int data, XtPointer call_data)
  183. {
  184.     pipe_int_write( data );
  185. }
  186.  
  187. /*
  188.  *  Generic scales callbacks : VOLUME and LOCATOR
  189.  */
  190. void Generic_scaleCB(Widget widget, int data, XtPointer call_data)
  191.     XmScaleCallbackStruct *cbs = (XmScaleCallbackStruct *) call_data;
  192.     
  193.     pipe_int_write(  data );
  194.     pipe_int_write(cbs->value);
  195. }
  196.  
  197. /* 
  198.  * Detect when a mouse button is pushed or released in a scale area to
  199.  * avoid concurent scale value modification while holding it with the mouse
  200.  */
  201. void Locator_btn(Widget w,XtPointer client_data,XEvent *event,Boolean *cont)
  202.     /* Type = ButtonPress or ButtonRelease */
  203.     locator_scale_button= event->xbutton.type;
  204. }
  205.  
  206. /*
  207.  * File List selection CALLBACK
  208.  */
  209. void File_ListCB(Widget widget, int data, XtPointer call_data)
  210. {
  211.     XmListCallbackStruct *cbs= (XmListCallbackStruct *) call_data;
  212.     char *text;
  213.     int nbvisible, first_visible ;
  214.     Arg al[10];
  215.     int ac;
  216.     
  217.     /* First, check that the selected file is really visible in the list */
  218.     ac=0;
  219.     XtSetArg(al[ac],XmNtopItemPosition,&first_visible); ac++;
  220.     XtSetArg(al[ac],XmNvisibleItemCount,&nbvisible); ac++;
  221.     XtGetValues(widget, al, ac);
  222.      
  223.     if ( ( first_visible > cbs->item_position) ||
  224.          ((first_visible+nbvisible) <= cbs->item_position))
  225.     XmListSetPos(widget, cbs->item_position);
  226.  
  227.     /* Tell the application to play the requested file */
  228.     XmStringGetLtoR(cbs->item,char_set,&text);
  229.     pipe_int_write(MOTIF_PLAY_FILE);
  230.     pipe_string_write(text);
  231.     file_number_to_play=cbs->item_position;
  232.     XtFree(text);
  233. }
  234.  
  235. /*
  236.  * Generic menu callback
  237.  */
  238. void menuCB(Widget w,int client_data,XmAnyCallbackStruct *call_data)
  239. {
  240.     switch (client_data)
  241.     {
  242.     case MENU_OPEN: 
  243.     {
  244.         XtManageChild(open_dialog);
  245.     }
  246.     break;
  247.     
  248.     case MENU_QUIT : {
  249.         pipe_int_write(MOTIF_QUIT);
  250.     }
  251.         break;
  252.     case MENU_TOGGLE : {
  253.         /* Toggle modified : for the moment , nothing to do ! */
  254.         /* if (XmToggleButtonGetState(w)) TRUE else FALSE */
  255.         }
  256.         break;
  257.     }
  258. }
  259.  
  260. /* 
  261.  * File selection box callback 
  262.  */
  263. void openCB(Widget w,int client_data,XmFileSelectionBoxCallbackStruct *call_data)
  264.     if (client_data==DIALOG_CANCEL)
  265.     { /* do nothing if cancel is selected. */
  266.         XtUnmanageChild(open_dialog);
  267.         return;
  268.     }
  269.     else if (client_data==DIALOG_ALL)
  270.     { /* Add all the listed files  */
  271.         Arg al[10];
  272.         int ac;
  273.         Widget the_list;
  274.         int nbfile;
  275.         XmStringTable files;
  276.         int i;
  277.                
  278.         the_list=XmFileSelectionBoxGetChild(open_dialog,XmDIALOG_LIST);
  279.         if (!XmIsList(the_list))
  280.         {
  281.             printf("PANIC: List are not what they used to be\n");
  282.             exit;
  283.         }
  284.         
  285.         ac=0;
  286.         XtSetArg(al[ac], XmNitemCount, &nbfile); ac++;
  287.         XtSetArg(al[ac], XmNitems, &files); ac++;
  288.         XtGetValues(the_list, al, ac);
  289.         
  290.         for (i=0;i<nbfile;i++)
  291.         XmListAddItemUnselected(file_list,files[i],0);
  292.     }
  293.     else
  294.     {   /* get filename from file selection box and add it to the list*/
  295.         XmListAddItemUnselected(file_list,call_data->value,0);
  296.         XtUnmanageChild(open_dialog);
  297.     }
  298. }
  299.  
  300.  
  301. /********************************************************
  302.  *                                                      *
  303.  * Receive DATA sent by the application on the pipe     *
  304.  *                                                      *
  305.  ********************************************************/
  306. void handle_input(client_data, source, id)
  307.     XtPointer client_data;
  308.     int *source;
  309.     XtInputId *id;
  310. {
  311.     int message;
  312.      
  313.     pipe_int_read(&message);
  314.  
  315.     switch (message)
  316.     {
  317.     case REFRESH_MESSAGE : {
  318.         printf("REFRESH MESSAGE IS OBSOLETE !!!\n");
  319.     }
  320.         break;
  321.         
  322.     case TOTALTIME_MESSAGE : { 
  323.         int cseconds;
  324.         int minutes,seconds;
  325.         char local_string[20];
  326.         Arg al[10];
  327.         int ac;
  328.  
  329.         pipe_int_read(&cseconds);
  330.         
  331.         seconds=cseconds/100;
  332.         minutes=seconds/60;
  333.         seconds-=minutes*60;
  334.         sprintf(local_string,"/ %i:%02i",minutes,seconds);
  335.         ac=0;
  336.         XtSetArg(al[ac], XmNlabelString,
  337.              XmStringCreate(local_string, char_set)); ac++;
  338.         XtSetValues(totlbl, al, ac);
  339.         
  340.         /* Readjust the time scale */
  341.         XmScaleSetValue(locator_scale,0);
  342.         ac=0;
  343.         XtSetArg(al[ac], XmNmaximum, cseconds); ac++;
  344.         XtSetValues(locator_scale, al, ac);
  345.         max_sec=cseconds;
  346.     }
  347.         break;
  348.         
  349.     case MASTERVOL_MESSAGE: { 
  350.         int volume;
  351.         
  352.         pipe_int_read(&volume);
  353.         XmScaleSetValue(volume_scale,volume);
  354.     }
  355.         break;
  356.         
  357.     case FILENAME_MESSAGE : {
  358.         char filename[255], separator[255];
  359.         Arg al[10];
  360.         char *pc;
  361.         int ac, i;
  362.         short nbcol;
  363.         
  364.         pipe_string_read(filename);
  365.  
  366.         /* Extract basename of the file */
  367.         pc=strrchr(filename,'/');
  368.         if (pc==NULL)
  369.         pc=filename;
  370.         else 
  371.         pc++;
  372.         
  373.         ac=0;
  374.         XtSetArg(al[ac], XmNlabelString,
  375.              XmStringCreate(pc, char_set)); ac++;
  376.         XtSetValues(file_namelbl, al, ac);
  377.         
  378.         /* Change the icon  */
  379.         ac=0;
  380.         XtSetArg(al[ac], XmNiconName,pc); ac++;
  381.         XtSetValues(toplevel,al,ac);
  382.  
  383.         /* Put a separator in the text Window */
  384.         ac=0;
  385.         XtSetArg(al[ac], XmNcolumns,&nbcol); ac++;
  386.         XtGetValues(text,al,ac);
  387.         
  388.         for (i=0;i<nbcol;i++)
  389.         separator[i]='*';
  390.         separator[i]='\0';
  391.  
  392.         XmTextInsert(text,wpr_position, separator);
  393.         wpr_position+= strlen(separator);
  394.         XmTextInsert(text,wpr_position++,"\n");
  395.         XtVaSetValues(text,XmNcursorPosition, wpr_position,NULL);
  396.         XmTextShowPosition(text,wpr_position);
  397.     }
  398.         break;
  399.     
  400.     case FILE_LIST_MESSAGE : {
  401.         char filename[255];
  402.         int i, number_of_files;
  403.         XmString s;
  404.         
  405.         /* reset the playing list : play from the start */
  406.         file_number_to_play=0;
  407.         
  408.         pipe_int_read(&number_of_files);
  409.         
  410.         for (i=0;i<number_of_files;i++)
  411.         {
  412.             pipe_string_read(filename);
  413.             s=XmStringCreate(filename,char_set);
  414.             XmListAddItemUnselected(file_list,s,0);
  415.             XmStringFree(s);
  416.         }
  417.     }
  418.         break;
  419.         
  420.     case NEXT_FILE_MESSAGE :
  421.     case PREV_FILE_MESSAGE : 
  422.     case TUNE_END_MESSAGE :{
  423.         Arg al[10];
  424.         int ac;
  425.         int nbfile;
  426.         
  427.         /* When a file ends, launch next if auto_next toggle */
  428.         if ((message==TUNE_END_MESSAGE) &&
  429.         !XmToggleButtonGetState(auto_next_option))
  430.         return;
  431.         
  432.         /* Total number of file to play in the list */
  433.         ac=0;
  434.         XtSetArg(al[ac], XmNitemCount, &nbfile); ac++;
  435.         XtGetValues(file_list, al, ac);
  436.         XmListDeselectAllItems(file_list); 
  437.         
  438.         if (message==PREV_FILE_MESSAGE)
  439.         file_number_to_play--;
  440.         else 
  441.         file_number_to_play++;
  442.  
  443.         /* Do nothing if requested file is before first one */
  444.         if (file_number_to_play<0)
  445.         {
  446.             file_number_to_play=1;
  447.             return;
  448.         }
  449.  
  450.         /* Stop after playing the last file */
  451.         if (file_number_to_play>nbfile)
  452.         { 
  453.             file_number_to_play=nbfile;
  454.             return;
  455.         }
  456.         
  457.         XmListSelectPos(file_list,file_number_to_play,TRUE);
  458.     }
  459.         break;
  460.  
  461.     case CURTIME_MESSAGE : { 
  462.         int cseconds;
  463.         int  sec,seconds, minutes;
  464.         int nbvoice;
  465.         char local_string[20];
  466.         Arg al[10];
  467.         int ac;
  468.  
  469.         pipe_int_read(&cseconds);
  470.         pipe_int_read(&nbvoice);
  471.         
  472.         sec=seconds=cseconds/100;
  473.         
  474.                 /* To avoid blinking */
  475.         if (sec!=last_sec)
  476.         {
  477.             minutes=seconds/60;
  478.             seconds-=minutes*60;
  479.             
  480.             sprintf(local_string,"%2d:%02d",
  481.                 minutes, seconds);
  482.         
  483.             ac=0;
  484.             XtSetArg(al[ac], XmNlabelString,
  485.                  XmStringCreate(local_string, char_set)); ac++;
  486.             XtSetValues(counterlbl, al, ac);
  487.         }
  488.  
  489.         last_sec=sec;
  490.         
  491.         /* Readjust the time scale if not dragging the scale */
  492.         if ( (locator_scale_button==ButtonRelease) &&
  493.          (cseconds<=max_sec))
  494.         XmScaleSetValue(locator_scale, cseconds);
  495.     }
  496.         break;
  497.         
  498.     case NOTE_MESSAGE : {
  499.         int channel;
  500.         int note;
  501.         
  502.         pipe_int_read(&channel);
  503.         pipe_int_read(¬e);
  504.         printf("NOTE chn%i %i\n",channel,note);
  505.     }
  506.         break;
  507.         
  508.     case    PROGRAM_MESSAGE :{
  509.         int channel;
  510.         int pgm;
  511.         
  512.         pipe_int_read(&channel);
  513.         pipe_int_read(&pgm);
  514.         printf("NOTE chn%i %i\n",channel,pgm);
  515.     }
  516.         break;
  517.         
  518.     case VOLUME_MESSAGE : { 
  519.         int channel;
  520.         int volume;
  521.         
  522.         pipe_int_read(&channel);
  523.         pipe_int_read(&volume);
  524.         printf("VOLUME= chn%i %i \n",channel, volume);
  525.     }
  526.         break;
  527.         
  528.         
  529.     case EXPRESSION_MESSAGE : { 
  530.         int channel;
  531.         int express;
  532.         
  533.         pipe_int_read(&channel);
  534.         pipe_int_read(&express);
  535.         printf("EXPRESSION= chn%i %i \n",channel, express);
  536.     }
  537.         break;
  538.         
  539.     case PANNING_MESSAGE : { 
  540.         int channel;
  541.         int pan;
  542.         
  543.         pipe_int_read(&channel);
  544.         pipe_int_read(&pan);
  545.         printf("PANNING= chn%i %i \n",channel, pan);
  546.     }
  547.         break;
  548.         
  549.     case  SUSTAIN_MESSAGE : { 
  550.         int channel;
  551.         int sust;
  552.         
  553.         pipe_int_read(&channel);
  554.         pipe_int_read(&sust);
  555.         printf("SUSTAIN= chn%i %i \n",channel, sust);
  556.     }
  557.         break;
  558.         
  559.     case  PITCH_MESSAGE : { 
  560.         int channel;
  561.         int bend;
  562.         
  563.         pipe_int_read(&channel);
  564.         pipe_int_read(&bend);
  565.         printf("PITCH BEND= chn%i %i \n",channel, bend);
  566.     }
  567.         break;
  568.         
  569.     case RESET_MESSAGE : {
  570.         printf("RESET_MESSAGE\n");
  571.     }
  572.         break;   
  573.         
  574.     case CLOSE_MESSAGE : {
  575.         printf("CLOSE_MESSAGE\n");
  576.         exit(0);
  577.     }
  578.         break;
  579.         
  580.     case CMSG_MESSAGE : { 
  581.         int type;
  582.         char message[1000];
  583.         
  584.         pipe_int_read(&type);
  585.         pipe_string_read(message);
  586.         
  587.         XmTextInsert(text,wpr_position, message);
  588.         wpr_position+= strlen(message);
  589.         XmTextInsert(text,wpr_position++,"\n");
  590.         XtVaSetValues(text,XmNcursorPosition, wpr_position,NULL);
  591.         XmTextShowPosition(text,wpr_position);
  592.     }
  593.         break;
  594.     default:    
  595.         fprintf(stderr,"UNKNOW MOTIF MESSAGE %i\n",message);
  596.     }
  597.     
  598. }
  599.  
  600. /* ***************************************
  601.  *                                       *
  602.  * Convenience function to create menus  *
  603.  *                                       *
  604.  *****************************************/
  605.  
  606. /* adds an accelerator to a menu option. */
  607. void add_accelerator(Widget w,char *acc_text,char *key)
  608. {
  609.     int ac;
  610.     Arg al[10];
  611.     
  612.     ac=0;
  613.     XtSetArg(al[ac],XmNacceleratorText,
  614.          XmStringCreate(acc_text,char_set)); ac++;
  615.     XtSetArg(al[ac],XmNaccelerator,key); ac++;
  616.     XtSetValues(w,al,ac);
  617. }
  618.  
  619. /* Adds a toggle option to an existing menu. */
  620. Widget make_menu_toggle(char *item_name, int client_data, Widget menu)
  621. {
  622.     int ac;
  623.     Arg al[10];
  624.     Widget item;
  625.  
  626.     ac = 0;
  627.     XtSetArg(al[ac],XmNlabelString, XmStringCreateLtoR(item_name,
  628.                                char_set)); ac++;
  629.     item=XmCreateToggleButton(menu,item_name,al,ac);
  630.     XtManageChild(item);
  631.     XtAddCallback(item, XmNvalueChangedCallback, 
  632.           (XtCallbackProc) menuCB,(XtPointer) client_data);
  633.     XtSetSensitive(item, True);
  634.     return(item);
  635. }
  636.  
  637. /* Adds an option to an existing menu. */
  638. Widget make_menu_option(char *option_name, KeySym mnemonic,
  639.             int client_data, Widget menu)
  640. {
  641.     int ac;
  642.     Arg al[10];
  643.     Widget b;
  644.     
  645.     ac = 0;
  646.     XtSetArg(al[ac], XmNlabelString,
  647.          XmStringCreateLtoR(option_name, char_set)); ac++;
  648.     XtSetArg (al[ac], XmNmnemonic, mnemonic); ac++;
  649.     b=XtCreateManagedWidget(option_name,xmPushButtonWidgetClass,
  650.                 menu,al,ac);
  651.     XtAddCallback (b, XmNactivateCallback,
  652.            (XtCallbackProc) menuCB, (XtPointer) client_data);
  653.     return(b);
  654. }
  655.  
  656. /* Creates a new menu on the menu bar. */
  657. Widget make_menu(char *menu_name,KeySym  mnemonic, Widget menu_bar)
  658. {
  659.     int ac;
  660.     Arg al[10];
  661.     Widget menu, cascade;
  662.  
  663.     ac = 0;
  664.     menu = XmCreatePulldownMenu (menu_bar, menu_name, al, ac);
  665.  
  666.     ac = 0;
  667.     XtSetArg (al[ac], XmNsubMenuId, menu); ac++;
  668.     XtSetArg (al[ac], XmNmnemonic, mnemonic); ac++;
  669.     XtSetArg(al[ac], XmNlabelString,
  670.         XmStringCreateLtoR(menu_name, char_set)); ac++;
  671.     cascade = XmCreateCascadeButton (menu_bar, menu_name, al, ac);
  672.     XtManageChild (cascade); 
  673.  
  674.     return(menu);
  675. }
  676.  
  677. /* *******************************************
  678.  *                                           *
  679.  * Interface initialisation before launching *
  680.  *                                           *
  681.  *********************************************/
  682.  
  683. void create_menus(Widget menu_bar)
  684. {
  685.     Widget menu;
  686.     
  687.     menu=make_menu("File",'F',menu_bar);
  688.     open_option = make_menu_option("Open", 'O', MENU_OPEN, menu);
  689.     add_accelerator(open_option, "meta+o", "Meta<Key>o:");
  690.     
  691.     quit_option = make_menu_option("Exit", 'E', MENU_QUIT, menu);
  692.     add_accelerator(quit_option, "meta+q", "Meta<Key>q:");
  693.  
  694.     menu=make_menu("Options",'O',menu_bar);
  695.     auto_next_option= make_menu_toggle("Auto Next", MENU_TOGGLE, menu);
  696.     XmToggleButtonSetState( auto_next_option , True , False );
  697.  
  698.  
  699. }
  700.  
  701. void create_dialog_boxes()
  702. {
  703.     Arg al[10];
  704.     int ac;
  705.     XmString add_all = XmStringCreateLocalized("ADD ALL");
  706.   
  707.     /* create the file selection box used by MENU_OPEN */
  708.     ac=0;
  709.     XtSetArg(al[ac],XmNmustMatch,True); ac++;
  710.     XtSetArg(al[ac],XmNautoUnmanage,False); ac++;
  711.     XtSetArg(al[ac],XmNdialogTitle,
  712.          XmStringCreateLtoR("TIMIDITY: Open",char_set)); ac++;
  713.     open_dialog=XmCreateFileSelectionDialog(toplevel,"open_dialog",al,ac);
  714.     XtAddCallback(open_dialog, XmNokCallback, 
  715.           (XtCallbackProc) openCB, (XtPointer) DIALOG_OK);
  716.     XtAddCallback(open_dialog, XmNcancelCallback, 
  717.           (XtCallbackProc) openCB, (XtPointer) DIALOG_CANCEL);
  718.     XtUnmanageChild(XmFileSelectionBoxGetChild(open_dialog, XmDIALOG_HELP_BUTTON));
  719.     
  720.     ac = 0;
  721.     XtSetArg(al[ac], XmNleftOffset, 10); ac++;
  722.     XtSetArg(al[ac], XmNrightOffset, 10); ac++;
  723.     XtSetArg(al[ac], XmNtopOffset, 10); ac++;
  724.     XtSetArg(al[ac], XmNbottomOffset, 10); ac++;
  725.     XtSetArg(al[ac], XmNlabelString, add_all); ac++;
  726.     add_all_button = XmCreatePushButton(open_dialog, "add_all",al, ac);
  727.     XtManageChild(add_all_button); 
  728.     XtAddCallback(add_all_button, XmNactivateCallback,
  729.           (XtCallbackProc) openCB, (XtPointer) DIALOG_ALL);
  730. }
  731.  
  732. void Launch_Motif_Process(int pipe_number)
  733. {
  734.     Arg al[20];
  735.     int ac;
  736.     int argc=0;
  737.  
  738.     /* create the toplevel shell */
  739.     toplevel = XtAppInitialize(&context,"timidity",NULL,0,&argc,NULL,
  740.                    NULL,NULL,0);
  741.     
  742.     /*******************/
  743.     /* Main form       */
  744.     /*******************/
  745.     ac=0;
  746.     XtSetArg(al[ac],XmNtopAttachment,XmATTACH_FORM); ac++;
  747.     XtSetArg(al[ac],XmNbottomAttachment,XmATTACH_FORM); ac++;
  748.     XtSetArg(al[ac],XmNrightAttachment,XmATTACH_FORM); ac++;
  749.     XtSetArg(al[ac],XmNleftAttachment,XmATTACH_FORM); ac++;
  750.     
  751.     mainForm=XmCreateForm(toplevel,"form",al,ac);
  752.     XtManageChild(mainForm);
  753.  
  754.     CreatePixmaps(mainForm); 
  755.   
  756.  
  757.     /* create a menu bar and attach it to the form. */
  758.     ac=0;
  759.     XtSetArg(al[ac], XmNtopAttachment,   XmATTACH_FORM); ac++;
  760.     XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
  761.     XtSetArg(al[ac], XmNleftAttachment,  XmATTACH_FORM); ac++;
  762.     menu_bar=XmCreateMenuBar(mainForm,"menu_bar",al,ac);
  763.     XtManageChild(menu_bar);
  764.     
  765.     create_dialog_boxes();
  766.     create_menus(menu_bar);
  767.  
  768.     /*******************/
  769.     /* Message window  */
  770.     /*******************/
  771.     
  772.     ac=0;
  773.     XtSetArg(al[ac], XmNleftOffset, 10); ac++;
  774.     XtSetArg(al[ac], XmNrightOffset, 10); ac++;
  775.     XtSetArg(al[ac], XmNtopOffset, 10); ac++;
  776.     XtSetArg(al[ac], XmNbottomOffset, 10); ac++;
  777.     XtSetArg(al[ac],XmNtopAttachment,XmATTACH_WIDGET); ac++;
  778.     XtSetArg(al[ac],XmNtopWidget, menu_bar); ac++;
  779.     XtSetArg(al[ac],XmNrightAttachment,XmATTACH_FORM); ac++;
  780.     XtSetArg(al[ac],XmNleftAttachment,XmATTACH_FORM); ac++;
  781.     XtSetArg(al[ac],XmNeditMode,XmMULTI_LINE_EDIT); ac++;
  782.     XtSetArg(al[ac],XmNrows,10); ac++;
  783.     XtSetArg(al[ac],XmNcolumns,10); ac++;
  784.     XtSetArg(al[ac],XmNeditable, False); ac++;
  785.     XtSetArg(al[ac],XmNwordWrap, True); ac++;
  786.     XtSetArg(al[ac],XmNvalue, "TIMIDIY RUNNING...\n"); ac++;
  787.     wpr_position+= strlen("TIMIDIY RUNNING...\n");
  788.     
  789.     text=XmCreateScrolledText(mainForm,"text",al,ac);
  790.     XtManageChild(text);    
  791.    
  792.     /********************/ 
  793.     /* File_name label  */
  794.     /********************/
  795.     ac = 0;
  796.     XtSetArg(al[ac], XmNleftOffset, 20); ac++;
  797.     XtSetArg(al[ac], XmNrightOffset, 10); ac++;
  798.     XtSetArg(al[ac], XmNtopOffset, 20); ac++;
  799.     XtSetArg(al[ac], XmNbottomOffset, 20); ac++;
  800.     XtSetArg(al[ac], XmNlabelType, XmSTRING); ac++;
  801.     XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
  802.     XtSetArg(al[ac], XmNtopWidget, text); ac++;
  803.     XtSetArg(al[ac], XmNleftAttachment,XmATTACH_FORM); ac++;
  804.     XtSetArg(al[ac], XmNtraversalOn, False); ac++;
  805.     XtSetArg(al[ac], XmNhighlightThickness,0); ac++;
  806.     XtSetArg(al[ac], XmNalignment,XmALIGNMENT_END); ac++;
  807.     XtSetArg(al[ac], XmNlabelString,
  808.          XmStringCreate("Playing:",char_set)); ac++;
  809.     file_headlbl = XmCreateLabel(mainForm,"fileheadlbl",al,ac);
  810.     XtManageChild(file_headlbl);
  811.     
  812.  
  813.     ac = 0;
  814.     XtSetArg(al[ac], XmNrightOffset, 10); ac++;
  815.     XtSetArg(al[ac], XmNtopOffset, 20); ac++;
  816.     XtSetArg(al[ac], XmNbottomOffset, 20); ac++;
  817.     XtSetArg(al[ac], XmNlabelType, XmSTRING); ac++;
  818.     XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
  819.     XtSetArg(al[ac], XmNtopWidget, text); ac++;
  820.     XtSetArg(al[ac], XmNleftAttachment,XmATTACH_WIDGET); ac++;
  821.     XtSetArg(al[ac], XmNleftWidget,file_headlbl); ac++;
  822.     XtSetArg(al[ac], XmNtraversalOn, False); ac++;
  823.     XtSetArg(al[ac], XmNhighlightThickness,0); ac++;
  824.     XtSetArg(al[ac], XmNalignment,XmALIGNMENT_BEGINNING); ac++;
  825.     XtSetArg(al[ac], XmNlabelString,
  826.          XmStringCreate("NONE           ",char_set)); ac++;
  827.     file_namelbl = XmCreateLabel(mainForm,"filenameLbl",al,ac);
  828.     XtManageChild(file_namelbl);
  829.  
  830.     /*****************************/
  831.     /* TIME LABELS IN A FORM     */
  832.     /*****************************/
  833.    
  834.     /* Counters frame    */
  835.     ac=0;
  836.     XtSetArg(al[ac], XmNtopOffset, 10); ac++;
  837.     XtSetArg(al[ac], XmNbottomOffset, 10); ac++;
  838.     XtSetArg(al[ac], XmNleftOffset, 10); ac++;
  839.     XtSetArg(al[ac], XmNrightOffset, 10); ac++;
  840.     XtSetArg(al[ac],XmNtopAttachment,XmATTACH_WIDGET); ac++;
  841.     XtSetArg(al[ac],XmNtopWidget,text); ac++;
  842.     XtSetArg(al[ac],XmNrightAttachment,XmATTACH_FORM); ac++;
  843.     /*
  844.       XtSetArg(al[ac],XmNleftAttachment,XmATTACH_WIDGET); ac++;
  845.       XtSetArg(al[ac],XmNleftWidget,file_namelbl); ac++;
  846.       */
  847.     XtSetArg(al[ac],XmNshadowType,XmSHADOW_OUT); ac++;
  848.     countFrame=XmCreateFrame(mainForm,"countframe",al,ac);
  849.     XtManageChild(countFrame);
  850.  
  851.     /* Counters form       */
  852.     ac=0;
  853.     XtSetArg(al[ac],XmNtopAttachment,XmATTACH_FORM); ac++;
  854.     XtSetArg(al[ac],XmNbottomAttachment,XmATTACH_FORM); ac++;
  855.     XtSetArg(al[ac],XmNrightAttachment,XmATTACH_FORM); ac++;
  856.     XtSetArg(al[ac],XmNleftAttachment,XmATTACH_FORM); ac++;
  857.     XtSetArg(al[ac],XmNleftAttachment,XmATTACH_FORM); ac++;
  858.    
  859.     countForm=XmCreateForm(countFrame,"countform",al,ac);
  860.     XtManageChild(countForm);
  861.      
  862.     /* HEADER label       */
  863.     ac = 0;
  864.     XtSetArg(al[ac], XmNtopOffset, 10); ac++;
  865.     XtSetArg(al[ac], XmNlabelType, XmSTRING); ac++;
  866.     XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
  867.     XtSetArg(al[ac], XmNleftAttachment,XmATTACH_FORM); ac++;
  868.     XtSetArg(al[ac], XmNrightAttachment,XmATTACH_FORM); ac++;
  869.     XtSetArg(al[ac], XmNtraversalOn, False); ac++;
  870.     XtSetArg(al[ac], XmNhighlightThickness,0); ac++;
  871.     XtSetArg(al[ac], XmNlabelString,
  872.          XmStringCreate("Tempus Fugit",char_set)); ac++;
  873.     count_headlbl = XmCreateLabel(countForm,"countheadLbl",al,ac);
  874.     XtManageChild(count_headlbl);
  875.  
  876.     /* current Time label       */
  877.     ac = 0;
  878.     XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
  879.     XtSetArg(al[ac], XmNtopWidget, count_headlbl); ac++;
  880.     XtSetArg(al[ac], XmNleftAttachment,XmATTACH_FORM); ac++;
  881.     XtSetArg(al[ac], XmNbottomAttachment,XmATTACH_FORM); ac++;
  882.     XtSetArg(al[ac], XmNtraversalOn, False); ac++;
  883.     XtSetArg(al[ac], XmNhighlightThickness,0); ac++;
  884.     XtSetArg(al[ac], XmNalignment,XmALIGNMENT_END); ac++;
  885.     XtSetArg(al[ac], XmNlabelString,
  886.          XmStringCreate("00:00",char_set)); ac++;
  887.     counterlbl = XmCreateLabel(countForm,"counterLbl",al,ac);
  888.     XtManageChild(counterlbl);
  889.     
  890.     /* Total time label */
  891.         
  892.     ac = 0;
  893.     XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
  894.     XtSetArg(al[ac], XmNtopWidget, count_headlbl); ac++;
  895.     XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
  896.     XtSetArg(al[ac], XmNleftWidget, counterlbl); ac++;
  897.     XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
  898.     XtSetArg(al[ac], XmNbottomAttachment,XmATTACH_FORM); ac++;
  899.     XtSetArg(al[ac], XmNtraversalOn, False); ac++;
  900.     XtSetArg(al[ac], XmNhighlightThickness,0); ac++;
  901.     XtSetArg(al[ac], XmNalignment,XmALIGNMENT_BEGINNING); ac++;
  902.     XtSetArg(al[ac], XmNlabelString,
  903.          XmStringCreate("/ 00:00",char_set)); ac++;
  904.     totlbl = XmCreateLabel(countForm,"TotalTimeLbl",al,ac);
  905.     XtManageChild(totlbl);
  906.             
  907.     /******************/ 
  908.     /* Locator Scale  */
  909.     /******************/
  910.     {    /*
  911.      * We need to add an xevent manager for buton pressing since 
  912.      * locator_scale is a critical ressource that can be modified
  913.      * by shared by the handle input function
  914.      */
  915.  
  916.     WidgetList WList;
  917.     Cardinal Card;
  918.  
  919.     ac = 0;
  920.     XtSetArg(al[ac], XmNleftOffset, 10); ac++;
  921.     XtSetArg(al[ac], XmNrightOffset, 10); ac++;
  922.     XtSetArg(al[ac], XmNtopOffset, 10); ac++;
  923.     XtSetArg(al[ac], XmNbottomOffset, 10); ac++;
  924.     XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
  925.     XtSetArg(al[ac], XmNtopWidget, countForm); ac++;
  926.     XtSetArg(al[ac], XmNleftAttachment,XmATTACH_FORM); ac++;
  927.     XtSetArg(al[ac], XmNrightAttachment,XmATTACH_FORM); ac++;
  928.     XtSetArg(al[ac], XmNmaximum, 100); ac++;
  929.     XtSetArg(al[ac], XmNminimum, 0); ac++;
  930.     XtSetArg(al[ac], XmNshowValue, True); ac++;
  931.     XtSetArg(al[ac], XmNdecimalPoints, 2); ac++;
  932.     XtSetArg(al[ac], XmNorientation, XmHORIZONTAL); ac++;
  933.     XtSetArg(al[ac], XmNtraversalOn, False); ac++;
  934.     XtSetArg(al[ac], XmNhighlightThickness,0); ac++;
  935.     locator_scale = XmCreateScale(mainForm,"locator",al,ac);
  936.     XtManageChild(locator_scale);
  937.     XtAddCallback(locator_scale,XmNvalueChangedCallback,
  938.               (XtCallbackProc) Generic_scaleCB, 
  939.               (XtPointer) MOTIF_CHANGE_LOCATOR);
  940.     
  941.     /* Reach the scrollbar child in the scale  */
  942.     ac = 0;
  943.     XtSetArg(al[ac], XtNchildren, &WList); ac++;    
  944.     XtSetArg(al[ac], XtNnumChildren, &Card); ac++;    
  945.     XtGetValues(locator_scale,al,ac);    
  946.     if ((Card!=2)||
  947.         strcmp(XtName(WList[1]),"Scrollbar"))
  948.         fprintf(stderr,"PANIC: Scale has be redefined.. may cause bugs\n");
  949.     
  950.      XtAddEventHandler(WList[1],ButtonPressMask|ButtonReleaseMask,
  951.               FALSE,Locator_btn,NULL);
  952.     }
  953.  
  954.     /*****************************/
  955.     /* Control buttons in a form */
  956.     /*****************************/
  957.     
  958.     /* create form for the row of control buttons */
  959.     ac = 0; 
  960.     XtSetArg(al[ac], XmNtopOffset, 10); ac++;
  961.     XtSetArg(al[ac], XmNbottomOffset, 10); ac++;
  962.     XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
  963.     XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
  964.     XtSetArg(al[ac],XmNtopAttachment,XmATTACH_WIDGET); ac++;
  965.     XtSetArg(al[ac], XmNtopWidget, locator_scale); ac++;
  966.     btnForm = XmCreateForm(mainForm,"btnForm", al, ac);
  967.     XtManageChild(btnForm);
  968.     
  969.     /* Previous Button */
  970.     ac = 0;
  971.     XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
  972.     XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
  973.     XtSetArg(al[ac], XmNleftOffset, 10); ac++;
  974.     XtSetArg(al[ac], XmNshadowType, XmSHADOW_OUT); ac++;
  975.     XtSetArg(al[ac], XmNlabelType, XmPIXMAP); ac++;
  976.     XtSetArg(al[ac], XmNlabelPixmap, prevPixmap); ac++;
  977.     XtSetArg(al[ac], XmNhighlightThickness, 2); ac++;
  978.     prevBtn = XmCreatePushButton(btnForm, "previous",al, ac);
  979.     XtManageChild(prevBtn);
  980.     XtAddCallback(prevBtn, XmNactivateCallback,
  981.           (XtCallbackProc) GenericCB, (XtPointer) MOTIF_PREV);
  982.  
  983.  
  984.     /* Backward Button */
  985.     ac = 0;
  986.     XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
  987.     XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
  988.     XtSetArg(al[ac], XmNleftWidget, prevBtn); ac++;
  989.     XtSetArg(al[ac], XmNleftOffset, 10); ac++;
  990.     XtSetArg(al[ac], XmNshadowType, XmSHADOW_OUT); ac++;
  991.     XtSetArg(al[ac], XmNlabelType, XmPIXMAP); ac++;
  992.     XtSetArg(al[ac], XmNlabelPixmap, backPixmap); ac++;
  993.     XtSetArg(al[ac], XmNhighlightThickness, 2); ac++;
  994.     backBtn = XmCreatePushButton(btnForm, "backward",al, ac);
  995.     XtManageChild(backBtn);
  996.     XtAddCallback(backBtn, XmNactivateCallback,
  997.           (XtCallbackProc) GenericCB, (XtPointer) MOTIF_RWD);
  998.  
  999.     /* Restart Button */
  1000.     ac = 0;
  1001.     XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
  1002.     XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
  1003.     XtSetArg(al[ac], XmNleftWidget, backBtn); ac++;
  1004.     XtSetArg(al[ac], XmNleftOffset, 2); ac++;
  1005.     XtSetArg(al[ac], XmNshadowType, XmSHADOW_OUT); ac++;
  1006.     XtSetArg(al[ac], XmNshadowThickness, 2); ac++;
  1007.     XtSetArg(al[ac], XmNlabelType, XmPIXMAP); ac++;
  1008.     XtSetArg(al[ac], XmNlabelPixmap, restartPixmap); ac++;
  1009.     XtSetArg(al[ac], XmNhighlightThickness, 2); ac++;
  1010.     restartBtn = XmCreatePushButton(btnForm,"restartBtn", al, ac);
  1011.     XtManageChild(restartBtn);
  1012.     XtAddCallback(restartBtn, XmNactivateCallback,
  1013.           (XtCallbackProc) GenericCB, (XtPointer) MOTIF_RESTART);
  1014.  
  1015.     /* Quit Button */
  1016.     ac = 0;
  1017.     XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
  1018.     XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
  1019.     XtSetArg(al[ac], XmNleftWidget, restartBtn); ac++;
  1020.     XtSetArg(al[ac], XmNleftOffset, 2); ac++;
  1021.     XtSetArg(al[ac], XmNshadowType, XmSHADOW_OUT); ac++;
  1022.     XtSetArg(al[ac], XmNshadowThickness, 2); ac++;
  1023.     XtSetArg(al[ac], XmNlabelType, XmPIXMAP); ac++;
  1024.     XtSetArg(al[ac], XmNlabelPixmap, quitPixmap); ac++;
  1025.     XtSetArg(al[ac], XmNhighlightThickness, 2); ac++;
  1026.     quitBtn = XmCreatePushButton(btnForm,"quitBtn", al, ac);
  1027.     XtManageChild(quitBtn);
  1028.     XtAddCallback(quitBtn, XmNactivateCallback,
  1029.           (XtCallbackProc) GenericCB, (XtPointer) MOTIF_QUIT);
  1030.  
  1031.     /* Pause Button */
  1032.  
  1033.     ac = 0;
  1034.     XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
  1035.     XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
  1036.     XtSetArg(al[ac], XmNleftWidget, quitBtn); ac++;
  1037.     XtSetArg(al[ac], XmNshadowType, XmSHADOW_OUT); ac++;
  1038.     XtSetArg(al[ac], XmNshadowThickness, 2); ac++;
  1039.     XtSetArg(al[ac], XmNlabelType, XmPIXMAP); ac++;
  1040.     XtSetArg(al[ac], XmNlabelPixmap, pausePixmap); ac++;
  1041.     XtSetArg(al[ac], XmNhighlightThickness, 2); ac++;
  1042.     pauseBtn =  XmCreatePushButton(btnForm,"pauseBtn", al, ac);
  1043.     XtManageChild(pauseBtn);
  1044.     XtAddCallback(pauseBtn, XmNactivateCallback,
  1045.           (XtCallbackProc) GenericCB,(XtPointer) MOTIF_PAUSE);
  1046.  
  1047.     /* Forward Button */
  1048.  
  1049.     ac = 0;
  1050.     XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
  1051.     XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
  1052.     XtSetArg(al[ac], XmNleftWidget,pauseBtn); ac++;
  1053.     XtSetArg(al[ac], XmNshadowType, XmSHADOW_OUT); ac++;
  1054.     XtSetArg(al[ac], XmNshadowThickness, 2); ac++;
  1055.     XtSetArg(al[ac], XmNlabelType, XmPIXMAP); ac++;
  1056.     XtSetArg(al[ac], XmNlabelPixmap, fwdPixmap); ac++;
  1057.     XtSetArg(al[ac], XmNhighlightThickness, 2); ac++;
  1058.     fwdBtn =  XmCreatePushButton(btnForm,"fwdBtn", al, ac);
  1059.     XtManageChild(fwdBtn);
  1060.     XtAddCallback(fwdBtn, XmNactivateCallback,
  1061.           (XtCallbackProc) GenericCB, (XtPointer) MOTIF_FWD);
  1062.  
  1063.     /* Next Button */
  1064.     ac = 0;
  1065.     XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
  1066.     XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
  1067.     XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
  1068.     XtSetArg(al[ac], XmNleftWidget, fwdBtn); ac++;
  1069.     XtSetArg(al[ac], XmNleftOffset, 2); ac++;
  1070.     XtSetArg(al[ac], XmNshadowType, XmSHADOW_OUT); ac++;
  1071.     XtSetArg(al[ac], XmNshadowThickness, 2); ac++;
  1072.     XtSetArg(al[ac], XmNlabelType, XmPIXMAP); ac++;
  1073.     XtSetArg(al[ac], XmNlabelPixmap, nextPixmap); ac++;
  1074.     XtSetArg(al[ac], XmNhighlightThickness, 2); ac++;
  1075.     nextBtn = XmCreatePushButton(btnForm,"nextBtn", al, ac);
  1076.     XtManageChild(nextBtn);
  1077.     XtAddCallback(nextBtn, XmNactivateCallback,
  1078.           (XtCallbackProc) GenericCB, (XtPointer) MOTIF_NEXT);
  1079.     
  1080.     /********************/
  1081.     /* Volume scale     */
  1082.     /********************/
  1083.     ac = 0;
  1084.     XtSetArg(al[ac], XmNleftOffset, 10); ac++;
  1085.     XtSetArg(al[ac], XmNrightOffset, 10); ac++;
  1086.     XtSetArg(al[ac], XmNtopOffset, 10); ac++;
  1087.     XtSetArg(al[ac], XmNbottomOffset, 10); ac++;
  1088.     XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
  1089.     XtSetArg(al[ac], XmNtopWidget, btnForm); ac++;
  1090.     XtSetArg(al[ac], XmNleftAttachment,XmATTACH_FORM); ac++;
  1091.     XtSetArg(al[ac], XmNbottomAttachment,XmATTACH_FORM); ac++;
  1092.  
  1093.     XtSetArg(al[ac], XmNmaximum, MAX_AMPLIFICATION); ac++;
  1094.     XtSetArg(al[ac], XmNminimum, 0); ac++;
  1095.     XtSetArg(al[ac], XmNshowValue, True); ac++;
  1096.  
  1097.     XtSetArg(al[ac], XmNtraversalOn, False); ac++;
  1098.     XtSetArg(al[ac], XmNhighlightThickness,0); ac++;
  1099.     XtSetArg(al[ac], XmNtitleString,
  1100.          XmStringCreate("VOL",char_set)); ac++;
  1101.     volume_scale = XmCreateScale(mainForm,"volscale",al,ac);
  1102.     XtManageChild(volume_scale);
  1103.     XtAddCallback(volume_scale, XmNvalueChangedCallback,
  1104.           (XtCallbackProc) Generic_scaleCB,
  1105.           (XtPointer) MOTIF_CHANGE_VOLUME);
  1106.   
  1107.   
  1108.     /********************/ 
  1109.     /* File list        */
  1110.     /********************/ 
  1111.     
  1112.     ac = 0;
  1113.     XtSetArg(al[ac], XmNtopOffset, 10); ac++;
  1114.     XtSetArg(al[ac], XmNbottomOffset, 10); ac++;
  1115.     XtSetArg(al[ac], XmNleftOffset, 10); ac++;
  1116.     XtSetArg(al[ac], XmNrightOffset, 10); ac++;
  1117.     XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
  1118.     XtSetArg(al[ac], XmNtopWidget, btnForm ); ac++;
  1119.     XtSetArg(al[ac], XmNleftAttachment,XmATTACH_WIDGET); ac++;
  1120.     XtSetArg(al[ac], XmNleftWidget, volume_scale); ac++;
  1121.     XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
  1122.     XtSetArg(al[ac], XmNbottomAttachment,XmATTACH_FORM); ac++;
  1123.  
  1124.     XtSetArg(al[ac], XmNselectionPolicy ,XmSINGLE_SELECT); ac++;
  1125.     XtSetArg(al[ac], XmNscrollBarDisplayPolicy ,XmAS_NEEDED); ac++;
  1126.     XtSetArg(al[ac], XmNlistSizePolicy ,XmRESIZE_IF_POSSIBLE); ac++;
  1127.  
  1128.     XtSetArg(al[ac], XmNtraversalOn, False); ac++;
  1129.     XtSetArg(al[ac], XmNhighlightThickness,0); ac++;
  1130.    
  1131.     file_list = XmCreateScrolledList(mainForm,"File List",al,ac);
  1132.     XtManageChild(file_list);
  1133.     XtAddCallback(file_list, XmNsingleSelectionCallback,
  1134.           (XtCallbackProc) File_ListCB,
  1135.           NULL);
  1136.  
  1137.     /*
  1138.      * Last details on toplevel
  1139.      */
  1140.     ac=0;
  1141.     /*
  1142.       XtSetArg(al[ac],XmNwidth,400); ac++;
  1143.       XtSetArg(al[ac],XmNheight,800); ac++;
  1144.       */
  1145.     XtSetArg(al[ac], XmNtitle, "Timidity 6.4f"); ac++;
  1146.     XtSetArg(al[ac], XmNiconName, "NONE"); ac++;
  1147.     XtSetArg(al[ac], XmNiconPixmap, timidityPixmap); ac++; 
  1148.     XtSetValues(toplevel,al,ac);
  1149.     
  1150.         
  1151.   /*******************************************************/ 
  1152.   /* Plug the pipe ..... and heeere we go                */
  1153.   /*******************************************************/ 
  1154.  
  1155.     XtAppAddInput(context,pipe_number, 
  1156.           (XtPointer) XtInputReadMask,handle_input,NULL);
  1157.     
  1158.     XtRealizeWidget(toplevel);
  1159.     XtAppMainLoop(context);
  1160. }
  1161.